package com.ruoyi.system.dao;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

/**
 * @Author 白菜不是菜 chenwen2@wdai.com
 * @Version V1.0
 * @Description
 * @Date 19-2-28 下午2:03
 **/
@Component
public class BaseDAO<T> {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

    public int queryForInt(String sql) {
        Object[] object = {};
        Integer cnt = queryForInt(getDoneSQL(sql), object);
        return cnt == null ? 0 : cnt.intValue();
    }

    public Integer queryForInt(final String sql, final Object[] o) {
        final String sqlDone = getDoneSQL(sql);
        Integer ret = jdbcTemplate.queryForObject(sqlDone, o, Integer.class);
        return ret;
    }

    public int queryForInt(String sql, Map m) {
        final String sqlDone = getDoneSQL(sql);
        return getNamedParameterJdbcTemplate().query(sqlDone, m, new ResultSetExtractor<Integer>() {
            public Integer extractData(ResultSet rs) throws SQLException, DataAccessException {
                return rs.next() ? rs.getInt(1) : 0;
            }
        });
    }

    public long queryForLong(String sql, Object[] o) {
        final String sqlDone = getDoneSQL(sql);
        return getJdbcTemplate().query(sqlDone, o, rs -> rs!=null ? rs.getLong(1) : 0l);
    }

    public BigDecimal queryForBigdecimal(final String sql, final Object[] o) {
        final String sqlDone = getDoneSQL(sql);
        BigDecimal result = getJdbcTemplate().query(sqlDone, o, resultSet -> resultSet != null ? resultSet.getBigDecimal(0) : BigDecimal.ZERO);
        return result;
    }

    public T queryForBean(Class<T> beanClass, String sql, Object[] args) {
        Object obj;
        try {
            String sqlDone = getDoneSQL(sql);
            obj = jdbcTemplate.queryForObject(sqlDone, new BeanPropertyRowMapper(beanClass), args);
        } catch (EmptyResultDataAccessException e) {
            return null;
        }
        return (T) obj;
    }

    public List<T> queryForList(Class<T> beanClass, String sql, Object[] args) {
        String sqlDone = getDoneSQL(sql);
        BeanPropertyRowMapper<T> rowMapper = new BeanPropertyRowMapper<>(beanClass);
        List<T> list = jdbcTemplate.query(sqlDone, rowMapper, args);
        return list;
    }

    public Map<String, Object> queryForMap(String sql, Object[] args) {
        String sqlDone = getDoneSQL(sql);
        Map map;
        try {
            map = jdbcTemplate.queryForMap(sqlDone, args);
        } catch (EmptyResultDataAccessException e) {
            e.printStackTrace();
            map = null;
        }
        return map;
    }


    public List<Map<String, Object>> queryForList(String sql, Object[] args) {
        String sqlDone = getDoneSQL(sql);
        List<Map<String, Object>> list = jdbcTemplate.queryForList(sqlDone, args);
        return list;
    }

    public List<Map<String, Object>> queryForList(String sql, Map args) {
        String sqlDone = getDoneSQL(sql);
        List<Map<String, Object>> list = namedParameterJdbcTemplate.queryForList(sqlDone, args);
        return list;
    }

    public int update(String sql, Object[] args) {
        String sqlDone = getDoneSQL(sql);
        int i = jdbcTemplate.update(sqlDone, args);
        return i;
    }

    public int update(String sql, Map map) {
        String sqlDone = getDoneSQL(sql);
        int i = namedParameterJdbcTemplate.update(sqlDone, map);
        return i;
    }

    /**
     * 插入数据并返回主键
     * @param sql
     * @param o
     * @return
     */
    public int insert(String sql, Object o) {
        KeyHolder holder = new GeneratedKeyHolder();
        String sqlDone = getDoneSQL(sql);
        namedParameterJdbcTemplate.update(sqlDone, new BeanPropertySqlParameterSource(o), holder);
        return holder.getKey().intValue();

    }

    public int execute(String sql) {
        Object[] object = {};
        return execute(sql, object);
    }

    public int execute(String sql, Object[] args) {
        return update(sql, args);
    }

    public int execute(String sql, Map<String, ?> map) {
        String sqlDone = getDoneSQL(sql);
        int i = jdbcTemplate.update(sqlDone, map);
        return i;
    }

    public int[] batchUpdate(String sql, List<Object[]> batchArgs) {
        String sqlDone = getDoneSQL(sql);
        int[] temp = jdbcTemplate.batchUpdate(sqlDone, batchArgs);
        return temp;
    }


    public JdbcTemplate getJdbcTemplate() {
        return jdbcTemplate;
    }

    public NamedParameterJdbcTemplate getNamedParameterJdbcTemplate() {
        return namedParameterJdbcTemplate;
    }

    /**
     * 处理SQL语句表前缀，格式化等
     *
     * @param sql sql语句
     * @return
     */
    public String getDoneSQL(String sql) {
        return sql;
    }

}
